from datetime import datetime
import logging
from core.entities.account_role import AccountWrap
from extensions.ext_database import db
from models.robot.rob_emoji import EmojiEmotionMap, EmojiType, RobEmoPackMap, RobEmoji, RobEmojiPack
from services.errors.emoji import EmojiCreatePrameterError, EmojiNotExistError, EmojiPackCreatePrameterError, EmojiPackageNotExistError
from flask_babel import _

from services.log_service import LogAction, LogService
class EmojiService:
    @staticmethod
    def create_emoji(account:AccountWrap,args:dict,ip_addr:str)->RobEmoji:
        if not account or not isinstance(account, AccountWrap):
            raise NotLoginError()
        file_id = args.get('file_id',None)
        file_url = args.get('file_url',None)
        if not file_id and not file_url:
            raise EmojiCreatePrameterError(_("Emoji file or url at least one is required"))
        if not args.get("emoji_code",None):
            raise EmojiCreatePrameterError(_("Emoji code is required"))
        if "emoji_map" in args and args["emoji_map"]:
            emoji_map ={"items":args["emoji_map"]}
        else:
            emoji_map = {}
        try:
            emoji_pack = None
            if "emoji_pack_id" in args and args["emoji_pack_id"]:
                emoji_pack = db.session.get(RobEmojiPack,args["emoji_pack_id"])
                if not emoji_pack:
                    raise EmojiPackageNotExistError(args["emoji_pack_id"])
            else:
                raise EmojiCreatePrameterError(_("Emoji pack is required"))
            emoji = RobEmoji(
                tenant_id = account.current_tenant_id,# type:ignore
                file_id = file_id,# type:ignore
                file_url = file_url,# type:ignore
                name = args.get('name',None),# type:ignore
                descrip = args.get('descrip',None),# type:ignore
                emo_code = args.get('emoji_code',None),# type:ignore
                emo_type = args.get('emoji_type',None),# type:ignore
                emo_map = emoji_map, # type:ignore
                created_by = account.id,# type:ignore
                
            )
            db.session.add(emoji)
            db.session.flush()
            if emoji_pack:
                emoji_map = RobEmoPackMap(
                    emoji_id = emoji.id,# type:ignore
                    pack_id = emoji_pack.id,# type:ignore
                    created_by = account.id,# type:ignore
                )
                db.session.add(emoji_map)
            LogService.log(
                account.current_tenant_id,
                account.id,
                LogAction.CREATE_EMOJI,
                content=f"{account.name} create emoji {emoji.name}:{emoji.emo_code}",
                created_ip=ip_addr,
                submit=False,
            )
            db.session.commit()
            return emoji
        except Exception as e:
            db.session.rollback()
            raise e
        
    @staticmethod
    def update_emoji(account:AccountWrap,args:dict,ip_addr:str)->RobEmoji:
        if not account or not isinstance(account, AccountWrap):
            raise NotLoginError()
        emoji_id = args.get('id',"")
        file_id = args.get('file_id',None)
        file_url = args.get('file_url',None)
        if not file_id and not file_url:
            raise EmojiCreatePrameterError(_("Emoji file or url at least one is required"))
        if file_id and file_url:
            raise EmojiCreatePrameterError(_("Emoji file and url only one is allowed"))
        if not args.get("emoji_code",None):
            raise EmojiCreatePrameterError(_("Emoji code is required"))
        emoji_code = args["emoji_code"]
        emoji_type = args["emoji_type"]
        descrip = args.get("descrip","")
        name = args["name"]
        if "emoji_map" in args and args["emoji_map"]:
            emoji_map ={"items":args["emoji_map"]}
        else:
            emoji_map = {}
        try:
            emoji = db.session.get(RobEmoji,emoji_id)
            if not emoji:
                raise EmojiNotExistError(emoji_id)
            if file_id:
                emoji.file_id = file_id
            elif file_url:
                emoji.file_url = file_url
            else:
                raise EmojiCreatePrameterError(_("Emoji file and url only one is allowed")) 
            emoji.name = name
            emoji.descrip = descrip
            emoji.emo_code = emoji_code
            emoji.emo_type = emoji_type
            emoji.emo_map = emoji_map
            emoji.updated_at = datetime.now()
            emoji.created_by = account.id
            LogService.log(
                account.current_tenant_id,
                account.id,
                LogAction.UPDATE_EMOJI,
                content=f"{account.name} update emoji {emoji.name}:{emoji.emo_code}",
                created_ip=ip_addr,
                submit=False,
            )
            db.session.commit()
            return emoji
        except Exception as e:
            db.session.rollback()
            raise e

    @staticmethod
    def del_emoji(account:AccountWrap,emoji_id:str,ip_addr:str):
        emoji = db.session.get(RobEmoji,emoji_id)
        if not emoji:
            raise EmojiNotExistError(emoji_id)
        try:
            log_msg = f"{account.name} delete emoji:{emoji.id}:{emoji.emo_code}"
            db.session.delete(emoji)
            LogService.log(
                account.current_tenant_id,
                account.id,
                LogAction.DEL_EMOJI,
                log_msg,
                ip_addr,
                submit=False
            )
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            raise e
    @staticmethod
    def get_emoji_pack_dict_by_id(emoji_pack_id:str)->dict:
        if emoji_pack_id:
            emoji_pack = db.session.get(RobEmojiPack,emoji_pack_id)
            if not emoji_pack:
                raise EmojiPackageNotExistError(emoji_pack_id)
            return emoji_pack.to_dict()
        return {}
        
    @staticmethod
    def get_emoji_list(tenant_id,args)->dict:
        try:
            query = db.session.query(RobEmoji).filter(RobEmoji.tenant_id==tenant_id)
            total = 0
            has_more = False
            if "id" in args and args["id"]:
                query = query.filter(RobEmoji.id==args["id"])
                total = query.count()
            else:
                if "emoji_pack_id" in args and args["emoji_pack_id"]:
                    maps = db.session.query(RobEmoPackMap).filter(RobEmoPackMap.pack_id==args["emoji_pack_id"]).all()
                    emoji_ids = [emo_map.emoji_id for emo_map in maps]
                    query = query.filter(RobEmoji.id.in_(emoji_ids))
                if "emoji_code" in args and args["emoji_code"]:
                    query = query.filter(RobEmoji.emo_code.ilike(f"%{args["emoji_code"]}%"))
                if "emoji_type" in args and args["emoji_type"] and args["emoji_type"] in EmojiType.choices():
                    query = query.filter(RobEmoji.emo_type==args["emoji_type"])
                if "name" in args and args["name"]:
                    query = query.filter(RobEmoji.name.ilike(f"%{args["name"]}%"))
                total = query.count()
                if "page" in args and args["page"]>0 and "page_size" in args and args["page_size"]>0:
                    query = query.offset((args['page']-1)*args['page_size']).limit(args['page_size'])
                    has_more = total > args['page']*args['page_size']
            data = query.all()
            return {
                "total": total,
                "has_more": has_more,
                "data": data
            }
        except Exception as e:
            logging.error(e)
            return {
                "total": 0,
                "has_more": False,
                "data": []
            }
        
    @staticmethod
    def get_emoji_pack_list(tenant_id,args:dict)->dict:
        try:
            query = db.session.query(RobEmojiPack).filter(RobEmojiPack.tenant_id==tenant_id)
            total = 0
            has_more = False
            if "id" in args and args["id"]:
                query = query.filter(RobEmojiPack.id==args["id"])
                total = query.count()
            else:
                if "name" in args and args["name"]:
                    query = query.filter(RobEmojiPack.name.ilike(f"%{args["name"]}%"))
                total = query.count()
                if "page" in args and args["page"]>0 and "page_size" in args and args["page_size"]>0:
                    query = query.offset((args['page']-1)*args['page_size']).limit(args['page_size'])
                    has_more = total > args['page']*args['page_size']
                
            data = query.all()
            return {
                "total": total,
                "has_more": has_more,
                "data": data
            }
        except Exception as e:
            logging.error(e)
            return {
                "total": 0,
                "has_more": False,
                "data": []
            }
        
    @staticmethod
    def create_emoji_pack(account:AccountWrap,args,ip_addr)->RobEmojiPack:
        if not account or not isinstance(account,AccountWrap):
            raise NotLoginError()
        tenant_id = account.current_tenant_id
        name = args.get("name",None)
        agent_id = args.get("agent_id",None)
        descrip = args.get("descrip",None)
        price  = args.get("price",0.0)
        if price >0:
            price = price*1000
        if not name or not agent_id:
            raise EmojiPackCreatePrameterError(_("Name and agent_id are required."))
        try:
            exist_pack = db.session.query(RobEmojiPack).filter(RobEmojiPack.name==name).one_or_none()
            if exist_pack:
                raise EmojiPackCreatePrameterError(_("Already has a emoji pack named {name}").format(name=name))
            pack = RobEmojiPack(
                tenant_id=tenant_id, #type:ignore
                name=name, #type:ignore
                descrip=descrip, #type:ignore
                price=price, #type:ignore
                agent_id=agent_id, #type:ignore
                created_by=account.id, #type:ignore
            )
            db.session.add(pack)
            db.session.flush()
            LogService.log(
                tenant_id=tenant_id,
                account_id=account.id,
                action=LogAction.CREATE_EMOJI_PACK,
                content=f"{account.name} create emoji package {pack.name}",
                created_ip=ip_addr,
                submit=False,
            )
            db.session.commit()
            return pack
        except Exception as e:
            db.session.rollback()
            raise e
        
        
    @staticmethod
    def update_emoji_pack(account:AccountWrap,args,ip_addr)->RobEmojiPack:
        if not account or not isinstance(account,AccountWrap):
            raise NotLoginError()
        tenant_id = account.current_tenant_id
        name = args.get("name",None)
        agent_id = args.get("agent_id",None)
        descrip = args.get("descrip",None)
        price  = args.get("price",0.0)
        if price >0:
            price = price*1000
        if not name or not agent_id:
            raise EmojiPackCreatePrameterError(_("Name and agent_id are required."))
        try:
            pack = db.session.get(RobEmojiPack,args["id"])
            if not pack:
                raise EmojiPackageNotExistError(args.get("id","None"))
            pack.name = name
            pack.agent_id = agent_id
            pack.descrip = descrip
            pack.price = price
            pack.updated_at = datetime.now()
            pack.updated_by = account.id
            LogService.log(
                tenant_id=tenant_id,
                account_id=account.id,
                action=LogAction.UPDATE_EMOJI_PACK,
                content=f"{account.name} UPDATE emoji package {pack.name}",
                created_ip=ip_addr,
                submit=False,
            )
            db.session.commit()
            return pack
        except Exception as e:
            db.session.rollback()
            raise e
        
    @staticmethod
    def del_emoji_pack(account:AccountWrap,emoji_pack_id:str,ip_addr:str):
        pack = db.session.get(RobEmojiPack,emoji_pack_id)
        if not pack:
            raise EmojiPackageNotExistError(emoji_pack_id)
        try:
            log_msg = f"{account.name} delete emoji:{pack.id}:{pack.name}"
            db.session.delete(pack)
            LogService.log(
                account.current_tenant_id,
                account.id,
                LogAction.DEL_EMOJI,
                log_msg,
                ip_addr,
                submit=False
            )
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            raise e
        
    @staticmethod
    def get_emoji_pack_emoji_maps(emoji_pack_id)->dict:
        emoji_pack = db.session.get(RobEmojiPack,emoji_pack_id)
        emotion_map = {}
        for emotion in EmojiEmotionMap.choices():
            emotion_map[emotion] = None

        if emoji_pack:
            emojis= emoji_pack.get_emojis()
            for emoji in emojis:
                for emotion in emoji.emo_map.get("items",[]):
                    emotion_map[emotion] = emoji.emo_code
        return emotion_map